/*this module is coded by erek, 2009-12-12*/
#include "zdfl_parameter_define.h"
#include "I2C.h"
#include "SPI.h"
#include "md_OSD.h"
#include "dv_OSD.h"
#include "Printf.h"

#ifdef Keil_C51
extern CHARACTERINFO Unicode_Font_char_info[];  //use for unicode font
XDATA BYTE UnicodeIndexBuffer[8] _at_ 64;
#define UnicodeIndexStartAddress		0xf00000
#endif

BYTE Use_UnicodeFont=0;

static void WritePn(U16 Index, U8 val)
{
	ChangePage((U8)((Index>>8) & 0x0f));
	WriteTW88((U8)Index, val);
}

static U8 ReadPn(U16 Index)
{
	U8 val;

	ChangePage((U8)((Index>>8) & 0x0f));
	val = ReadTW88((U8)Index);

	return val;
}

static void OSDSoftReset(void)
{
	U8 val;
	
	val = ReadPn(OSD_CONTROL1) | 0x01;
	WritePn(OSD_CONTROL1, val);
}

static void OSDHardwareEnable(void)
{
	U8 val;
	
	val = ReadPn(OSD_CONTROL1) | 0x40;
	WritePn(OSD_CONTROL1, val);
}

void OSD_SetSourceMemoryPositionBase(U32 addr)
{
	WritePn(SOURCE_MEMORYBASE_H, (U8)(addr>>16));
	WritePn(SOURCE_MEMORYBASE_M, (U8)(addr>>8));
	WritePn(SOURCE_MEMORYBASE_L, (U8)addr);
}

U32 OSD_GetSourceMemoryPositionBase(void)
{
	U32 addr;

	addr = ReadPn(SOURCE_MEMORYBASE_H);
	addr = (addr<<8) + ReadPn(SOURCE_MEMORYBASE_M);
	addr = (addr<<8) + ReadPn(SOURCE_MEMORYBASE_L);

	return addr;
}

void OSD_SetSourceMemoryHSize(U8 w64)
{
	WritePn(SOURCE_MEMORY_HLENGTH, w64);
}

void OSD_SetDestinationMemoryPositionBase(U32 addr)
{
	WritePn(TARGET_MEMORYBASE_H, (U8)(addr>>16));
	WritePn(TARGET_MEMORYBASE_M, (U8)(addr>>8));
	WritePn(TARGET_MEMORYBASE_L, (U8)addr);
}

U32 OSD_GetDestinationMemoryPositionBase(void)
{
	U32 addr;

	addr = ReadPn(TARGET_MEMORYBASE_H);
	addr = (addr<<8) + ReadPn(TARGET_MEMORYBASE_M);
	addr = (addr<<8) + ReadPn(TARGET_MEMORYBASE_L);

	return addr;
}

void OSD_SetDestinationMemoryHSize(U8 w64)
{
	WritePn(TARGET_MEMORY_HLENGTH, w64);
}

void OSD_SetWindow0MemoryPositionBase(U32 addr)
{
	WritePn(WIN0_MEMORYBASE_H, (U8)(addr>>16));
	WritePn(WIN0_MEMORYBASE_M, (U8)(addr>>8));
	WritePn(WIN0_MEMORYBASE_L, (U8)addr);
}

void OSD_SetWindow0MemoryHSize(U8 w64)
{
	WritePn(WIN0_MEMORY_HLENGTH, w64);
}

void OSD_SetWindow0MemoryVSize(U8 h64)
{
	WritePn(WIN0_MEMORY_VLENGTH, h64);
}

static void SetWindow0MemoryHStartLocation(U16 x)
{
	WritePn(WIN0_MEMORYHSTART_H, (U8)(x>>8));
	WritePn(WIN0_MEMORYHSTART_L, (U8)x);
}

static void SetWindow0MemoryVStartLocation(U16 x)
{
	WritePn(WIN0_MEMORYVSTART_H, (U8)(x>>8));
	WritePn(WIN0_MEMORYVSTART_L, (U8)x);
}

static void SetWindow0MemoryPosition(U16 xp, U16 yp)
{
	SetWindow0MemoryHStartLocation(xp);
	SetWindow0MemoryVStartLocation(yp);
}

void OSD_SetWindow1MemoryPositionBase(U32 addr)
{
	WritePn(WIN1_MEMORYBASE_H, (U8)(addr>>16));
	WritePn(WIN1_MEMORYBASE_M, (U8)(addr>>8));
	WritePn(WIN1_MEMORYBASE_L, (U8)addr);
}

void OSD_SetWindow1MemoryHSize(U8 w64)
{
	WritePn(WIN1_MEMORY_HLENGTH, w64);
}

void OSD_SetWindow1MemoryVSize(U8 h64)
{
	WritePn(WIN1_MEMORY_VLENGTH, h64);
}

static void SetWindow1MemoryHStartLocation(U16 x)
{
	WritePn(WIN1_MEMORYHSTART_H, (U8)(x>>8));
	WritePn(WIN1_MEMORYHSTART_L, (U8)x);
}

static void SetWindow1MemoryVStartLocation(U16 x)
{
	WritePn(WIN1_MEMORYVSTART_H, (U8)(x>>8));
	WritePn(WIN1_MEMORYVSTART_L, (U8)x);
}

static void SetWindow1MemoryPosition(U16 xp, U16 yp)
{
	SetWindow1MemoryHStartLocation(xp);
	SetWindow1MemoryVStartLocation(yp);
}

void OSD_SetWindow4MemoryPositionBase(U32 addr)
{
	WritePn(WIN4_MEMORYBASE_H, (U8)(addr>>16));
	WritePn(WIN4_MEMORYBASE_M, (U8)(addr>>8));
	WritePn(WIN4_MEMORYBASE_L, (U8)addr);
}

void OSD_SetWindow4MemoryHSize(U8 w64)
{
	WritePn(WIN4_MEMORY_HLENGTH, w64);
}

void OSD_SetWindow4MemoryVSize(U8 h64)
{
	WritePn(WIN4_MEMORY_VLENGTH, h64);
}

static void SetWindow4MemoryHStartLocation(U16 x)
{
	WritePn(WIN4_MEMORYHSTART_H, (U8)(x>>8));
	WritePn(WIN4_MEMORYHSTART_L, (U8)x);
}

static void SetWindow4MemoryVStartLocation(U16 x)
{
	WritePn(WIN4_MEMORYVSTART_H, (U8)(x>>8));
	WritePn(WIN4_MEMORYVSTART_L, (U8)x);
}

static void SetWindow4MemoryPosition(U16 xp, U16 yp)
{
	SetWindow4MemoryHStartLocation(xp);
	SetWindow4MemoryVStartLocation(yp);
}

void OSD_SetWindowMemoryPosition(U8 WinNO, U16 xp, U16 yp)
{
	if (WinNO == 0) 
	{
		SetWindow0MemoryPosition(xp, yp);
	}
	else if (WinNO == 1)
	{
		SetWindow1MemoryPosition(xp, yp);
	}
	else if (WinNO == 2)
	{
		SetWindow4MemoryPosition(xp, yp);
	}
	else if (WinNO == 3)
	{
		SetWindow4MemoryPosition(xp, yp);
	}
}

static void LoadLUT_8Bit(U8 WinNO, U8* ptr)
{
	U16 i,count = 256;
	struct ST_LUT *lut;
	lut = (struct ST_LUT *)ptr;

	WritePn(OSD_LUT_CONTROL, WinNO<<6);

	for (i=0; i<count; i++)
	{
		WritePn(OSD_LUT_ADDRINDEX, i);
		WritePn(OSD_LUT_DATAR, lut->R);
		WritePn(OSD_LUT_DATAG, lut->G);
		WritePn(OSD_LUT_DATAB, lut->B);
		WritePn(OSD_LUT_DATAATTR, lut->dummy);
		lut++;
	}
}

//Added by Jason for special use
static void LoadLUT_4Bit(U8 WinNO, U8 *ptr)
{
	U16 i,count = 16;
	struct ST_LUT *lut;
	lut = (struct ST_LUT *)ptr;

	WritePn(OSD_LUT_CONTROL, WinNO<<6);

	for (i=0; i<count; i++)
	{
		WritePn(OSD_LUT_ADDRINDEX, i);
		WritePn(OSD_LUT_DATAR, lut->R);
		WritePn(OSD_LUT_DATAG, lut->G);
		WritePn(OSD_LUT_DATAB, lut->B);
		WritePn(OSD_LUT_DATAATTR, lut->dummy);
		lut++;
	}
}

void OSD_LoadLUT(U8 WinNO, U8 BitMode, const U8 *ptr)
{
	if (BitMode == 8)
		LoadLUT_8Bit(WinNO, ptr);
	else if (BitMode == 4)
		LoadLUT_4Bit(WinNO, ptr);
}

static void SetWindow0ScreenHStartLocation(U16 x)
{
	WritePn(WIN0_SCREENHSTART_H, (U8)(x>>8));
	WritePn(WIN0_SCREENHSTART_L, (U8)x);
}

static void SetWindow0HLength(U16 x)
{
	WritePn(WIN0_HLENGTH_H, (U8)(x>>8));
	WritePn(WIN0_HLENGTH_L, (U8)x);
}

static void SetWindow0ScreenVStartLocation(U16 x)
{
	WritePn(WIN0_SCREENVSTART_H, (U8)(x>>8));
	WritePn(WIN0_SCREENVSTART_L, (U8)x);
}

static void SetWindow0VLength(U16 x)
{
	WritePn(WIN0_VLENGTH_H, (U8)(x>>8));
	WritePn(WIN0_VLENGTH_L, (U8)x);
}

static void SetWindow0Info(U16 HStart, U16 HLength, U16 VStart, U16 VLength)
{
	SetWindow0ScreenHStartLocation(HStart);
	SetWindow0HLength(HLength);
	SetWindow0ScreenVStartLocation(VStart);
	SetWindow0VLength(VLength);
}

static void SetWindow1ScreenHStartLocation(U16 x)
{
	WritePn(WIN1_SCREENHSTART_H, (U8)(x>>8));
	WritePn(WIN1_SCREENHSTART_L, (U8)x);
}

static void SetWindow1HLength(U16 x)
{
	WritePn(WIN1_HLENGTH_H, (U8)(x>>8));
	WritePn(WIN1_HLENGTH_L, (U8)x);
}

static void SetWindow1ScreenVStartLocation(U16 x)
{
	WritePn(WIN1_SCREENVSTART_H, (U8)(x>>8));
	WritePn(WIN1_SCREENVSTART_L, (U8)x);
}

static void SetWindow1VLength(U16 x)
{
	WritePn(WIN1_VLENGTH_H, (U8)(x>>8));
	WritePn(WIN1_VLENGTH_L, (U8)x);
}

static void SetWindow1Info(U16 HStart, U16 HLength, U16 VStart, U16 VLength)
{
	SetWindow1ScreenHStartLocation(HStart);
	SetWindow1HLength(HLength);
	SetWindow1ScreenVStartLocation(VStart);
	SetWindow1VLength(VLength);
}

static void SetWindow4ScreenHStartLocation(U16 x)
{
	WritePn(WIN4_SCREENHSTART_H, (U8)(x>>8));
	WritePn(WIN4_SCREENHSTART_L, (U8)x);
}

static void SetWindow4HLength(U16 x)
{
	WritePn(WIN4_HLENGTH_H, (U8)(x>>8));
	WritePn(WIN4_HLENGTH_L, (U8)x);
}

static void SetWindow4ScreenVStartLocation(U16 x)
{
	WritePn(WIN4_SCREENVSTART_H, (U8)(x>>8));
	WritePn(WIN4_SCREENVSTART_L, (U8)x);
}

static void SetWindow4VLength(U16 x)
{
	WritePn(WIN4_VLENGTH_H, (U8)(x>>8));
	WritePn(WIN4_VLENGTH_L, (U8)x);
}

static void SetWindow4Info(U16 HStart, U16 HLength, U16 VStart, U16 VLength)
{
	SetWindow4ScreenHStartLocation(HStart);
	SetWindow4HLength(HLength);
	SetWindow4ScreenVStartLocation(VStart);
	SetWindow4VLength(VLength);
}

void OSD_SetWindowInfo(U8 WinNO, U16 HStart, U16 HLength, U16 VStart, U16 VLength)
{
	if (WinNO == 0)
		SetWindow0Info(HStart, HLength, VStart, VLength);
	else if (WinNO == 1)
		SetWindow1Info(HStart, HLength, VStart, VLength);
	else if (WinNO == 2)
		SetWindow4Info(HStart, HLength, VStart, VLength);
	else if (WinNO == 3)
		SetWindow4Info(HStart, HLength, VStart, VLength);
}

void OSD_SetBitmapColorWriteMode(U8 mode)
{
	WritePn(OSD_MODE, mode); 
}

static void SetSourceStartLocation(U16 x, U16 y)
{
	WritePn(SOURCE_HSTART_H, (U8)(x>>8));
	WritePn(SOURCE_HSTART_L, (U8)x);
	WritePn(SOURCE_VSTART_H, (U8)(y>>8));
	WritePn(SOURCE_VSTART_L, (U8)y);
}

static void SetSourceDestinationSize(U16 x, U16 y)
{
	WritePn(TRANSFER_HLENGTH_H, (U8)(x>>8));
	WritePn(TRANSFER_HLENGTH_L, (U8)x);
	WritePn(TRANSFER_VLENGTH_H, (U8)(y>>8));
	WritePn(TRANSFER_VLENGTH_L, (U8)y);
}

static void SetDestinationStartLocation(U16 x, U16 y)
{
	WritePn(TARGET_HSTART_H, (U8)(x>>8));
	WritePn(TARGET_HSTART_L, (U8)x);
	WritePn(TARGET_VSTART_H, (U8)(y>>8));
	WritePn(TARGET_VSTART_L, (U8)y);
}

static void SetFillTransferBitmapWriteStart(U8 en)
{
	//U8 val;

	if (en == 1)
	{
		//val = ReadPn(OSD_STATUS);
		//WritePn(OSD_STATUS, (val|0x01));
		WritePn(OSD_STATUS, 0x01);
		//Printf("\n**OSD_STATUS1:%bx\r\n",ReadPn(OSD_STATUS));
	}
	else if (en == 0)
	{
		//val = ReadPn(OSD_STATUS);
		//WritePn(OSD_STATUS, (val&0xfe));
		WritePn(OSD_STATUS, 0x00);
		//Printf("\n**OSD_STATUS0:%bx\r\n",ReadPn(OSD_STATUS));
	}
}

static U8 GetTransferFillStatusIfDone(void)
{
	U8 val;

	val = ReadPn(OSD_STATUS);
	if ((val & 0x80) != 0)
		return 1;
		//{return 1;
		//Printf("\n**OSD_STATUS10:%bx\r\n",ReadPn(OSD_STATUS));}
	
	//Printf("\n**OSD_STATUS11:%bx\r\n",ReadPn(OSD_STATUS));
	return 0;
}

static void SetWindow4OSDFormat(U8 Format)
{
	U8 osdformat;
	
	osdformat = ReadPn(WIN4_CONTROL) & 0xf1;
	WritePn(WIN4_CONTROL, osdformat | Format);// 000=YCbCr422, 001=RGB565, 010=RGB4444, 011=RGB1444
}

static void SetFillColor(U16 color, U8 DispMode)
{
	if (DispMode == 16)
	{
		WritePn(OSD_FILLCOLOR_H, (BYTE)(color>>8));
		WritePn(OSD_FILLCOLOR_L, (BYTE)color);
	}
	else if (DispMode == 8)
	{
		WritePn(OSD_FILLCOLOR_L, (BYTE)color);
	}
}

static void SetBlockFillEnable(U8 DispMode)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val = val & 0x00;//val&0xfb;//val&0x04;	//protect the byte number per pixel

	if (DispMode == 16)
		OSD_SetBitmapColorWriteMode(val|0x80|0x30|0x00|0x00);//BLOCKFILL | BLT_NO | CONV_DIS |   Bit expansion
	else if (DispMode == 8)
		OSD_SetBitmapColorWriteMode(val|0x80|0x30|0x04|0x00);//BLOCKFILL | BLT_NO | CONV_DIS |   Bit expansion	
}

void OSD_BlockFill(U16 dx, U16 dy, U16 w, U16 h, U16 color, U8 DispMode)
{
	SetDestinationStartLocation(dx,dy);
	SetSourceDestinationSize(w,h);
	SetFillColor(color,DispMode);
	//Printf("\ncolor:%x\r\n",color);
	SetBlockFillEnable(DispMode);

	if (DispMode == 16)
		SetWindow4OSDFormat(RGB565);

	//OSDSoftReset();
	
	SetFillTransferBitmapWriteStart(1);

	while (GetTransferFillStatusIfDone())
		;

	SetFillTransferBitmapWriteStart(0);
}

static void SetBlockTransferEnable(U8 DispMode)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val = val & 0x38;	//protect the color conversion,selective overwrite

	if (DispMode == 16)
		OSD_SetBitmapColorWriteMode(val|0x40|0x00);//BLOCKTransfer  |   Bit expansion
	else if (DispMode == 8)
		OSD_SetBitmapColorWriteMode(val|0x40|0x04|0x00);//BLOCKTransfer  |   Bit expansion
}

void OSD_BlockTransfer(U16 sx, U16 sy, U16 w, U16 h, U16 dx, U16 dy,U8 DispMode)
{
	//Printf("\nsx=%d,sy=%d,w=%d,h=%d,dx=%d,dy=%d,DispMode=%bd\r\n",sx,sy,w,h,dx,dy,DispMode);
	SetSourceStartLocation(sx, sy);
	SetSourceDestinationSize(w, h);
	SetDestinationStartLocation(dx, dy);
	
	SetBlockTransferEnable(DispMode);
	SetFillTransferBitmapWriteStart(1);

	while (GetTransferFillStatusIfDone())
		;

	SetFillTransferBitmapWriteStart(0);
}

#ifndef DP80390
static void SetBlockTransferLinearEnable(U8 DispMode)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val = val & 0x38;	//protect the color conversion,selective overwrite

	if (DispMode == 16)
		OSD_SetBitmapColorWriteMode(val|0xc0|0x00);//BLOCKTransfer  |   Bit expansion
	else if (DispMode == 8)
		OSD_SetBitmapColorWriteMode(val|0xc0|0x04|0x00);//BLOCKTransfer  |   Bit expansion
}

void OSD_BlockTransferLinear(U32 addr, U16 w, U16 h, U16 dx, U16 dy, U8 DispMode) reentrant
{
	U32 addr_temp;

	addr_temp = OSD_GetSourceMemoryPositionBase();
	
	OSD_SetSourceMemoryPositionBase(addr);
	SetSourceStartLocation(0, 0);
	SetSourceDestinationSize(w, h);
	SetDestinationStartLocation(dx, dy);
	
	SetBlockTransferLinearEnable(DispMode);
	SetFillTransferBitmapWriteStart(1);

	while (GetTransferFillStatusIfDone())
		;

	SetFillTransferBitmapWriteStart(0);

	OSD_SetSourceMemoryPositionBase(addr_temp);
}
#endif

static void SetColorConvertEnable(void)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val &= 0xc7;
	OSD_SetBitmapColorWriteMode(val | 0x38);// Enable Color Conversion, No bitblit
	//WritePn(OSD_MODE, val | 0x38);  
}

void SetColorConvertDisable(void)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val &= 0xf7;
	OSD_SetBitmapColorWriteMode(val);// disable Color Conversion, No bitblit
	//WritePn(OSD_MODE, val);  
}

void OSD_ConvertColor(U8 colorNum,U16 *cvColor, U8 DispMode)
{
	int i, s, t;
	
	for (i=0; i<colorNum; i+=2)
	{
		s = cvColor[i]; 
		t = cvColor[i+1];
		if (DispMode == 16)
		{
			WritePn((CONVERSION_SOURCECOLOR1_H+i), (U8)(s>>8));
			WritePn((CONVERSION_SOURCECOLOR1_L+i), (U8)s);

			WritePn((CONVERSION_TARGETCOLOR1_H+i), (U8)(t>>8));
			WritePn((CONVERSION_TARGETCOLOR1_L+i), (U8)t);
		}
		else if (DispMode == 8)
		{
			WritePn((CONVERSION_SOURCECOLOR1_L+i), (U8)s);
			//Printf("\r\ns=%x",s);

			WritePn((CONVERSION_TARGETCOLOR1_L+i), (U8)t);
			//Printf("\r\nt=%x",t);
		}
	}

	SetColorConvertEnable();
}

static void SetSelectiveOvWriteEnable(void)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val &= 0xcf;

	OSD_SetBitmapColorWriteMode(val);// enable overwrite
	//Printf("\nOverwriteColor_val:%bx\r\n",val);
	//WritePn(OSD_MODE, val);  
}

void SetSelectiveOvWriteDisable(void)
{
	U8	val;

	val = ReadPn(OSD_MODE);
	val |= 0x30;

	OSD_SetBitmapColorWriteMode(val);// disable overwrite
	//WritePn(OSD_MODE, val);    
}

void OSD_OverWriteColor(U8 colorNum, U16 *cvColor,U8 DispMode)
{
	U8 i;
	
	for (i=0; i<colorNum; i++)
	{
		if (DispMode == 16)
		{
			WritePn((SELECTIVE_OVERWRITECOLOR1_H+i*2), (U8)(cvColor[i]>>8));
			WritePn((SELECTIVE_OVERWRITECOLOR1_L+i*2), (U8)cvColor[i]);
		}
		else if (DispMode == 8)
		{
			WritePn((SELECTIVE_OVERWRITECOLOR1_L+i*2), (U8)cvColor[i]);
		}
	}

	SetSelectiveOvWriteEnable();
}

static void SetWin0AlphaMode(U8 mode)
{
	// mode - 0: Global window alpha.
	//		  1: Per pixel alpha(win0 or win1), enable the color key alpha blending(win4);
	U8 val;

	val = ReadPn(WIN0_CONTROL);
	WritePn(WIN0_CONTROL, (val&0xcf) | (mode<<5));
}

static void SetWin0GlobalAlphaLevel(U8 level)
{
	//level - 0x00(min)~0x7f(max)
	WritePn(WIN0_GLOBALALPHA_VALUE, level);
}

static void SetWin1AlphaMode(U8 mode)
{
	// mode - 0: Global window alpha.
	//		  1: Per pixel alpha(win0 or win1), enable the color key alpha blending(win4);
	U8 val;

	val = ReadPn(WIN1_CONTROL);
	WritePn(WIN1_CONTROL, (val&0xcf) | (mode<<5));
}

static void SetWin1GlobalAlphaLevel(U8 level)
{
	//level - 0x00(min)~0x7f(max)
	WritePn(WIN1_GLOBALALPHA_VALUE, level);
}

static void SetWin4AlphaMode(U8 mode)
{
	// mode - 0: Global window alpha.
	//		  1: Per pixel alpha(win0 or win1), enable the color key alpha blending(win4);
	U8 val;

	val = ReadPn(WIN4_CONTROL);
	WritePn(WIN4_CONTROL, (val&0xcf) | (mode<<5));
}

static void SetWin4GlobalAlphaLevel(U8 level)
{
	//level - 0x00(min)~0x7f(max)
	WritePn(WIN4_GLOBALALPHA_VALUE, level);
}

static void SetWin4KeyAlphaColor(U8 colorNum, U16 *cvColor)
{
	U8 i;
	
	for (i=0; i<colorNum; i++)
	{	
		WritePn((WIN4_COLORKEY0_H+i*2), (U8)(cvColor[i]>>8));
		WritePn((WIN4_COLORKEY0_L+i*2), (U8)cvColor[i]);
	}
}

static void SetWin4KeyAlphaLevel(U8 Num, U8 level)
{
	U8 i;
	
	for (i=0; i<Num; i++)
	{	
		WritePn((WIN4_COLORKER0ALPHA_VALUE+i), level);
	}
}

static void OSD_AttrAlpha_Enable(U8 WinNO)
{
	U8 val;
	
	if (WinNO == 0)
	{
		val = ReadPn(WIN0_CONTROL);
		WritePn(WIN0_CONTROL, val|0x10);
	}
	else if (WinNO == 1)
	{
		val = ReadPn(WIN1_CONTROL);
		WritePn(WIN1_CONTROL, val|0x10);
	}
	else if (WinNO == 2)
	{
		val = ReadPn(WIN4_CONTROL);
		WritePn(WIN4_CONTROL, val|0x10);
	}
	else if (WinNO == 3)
	{
		val = ReadPn(WIN4_CONTROL);
		WritePn(WIN4_CONTROL, val|0x10);
	}
}

void OSD_AttrAlpha_Disable(U8 WinNO)
{
	U8 val;
	
	if (WinNO == 0)
	{
		val = ReadPn(WIN0_CONTROL);
		WritePn(WIN0_CONTROL, val&0xef);
	}
	else if (WinNO == 1)
	{
		val = ReadPn(WIN1_CONTROL);
		WritePn(WIN1_CONTROL, val&0xef);
	}
	else if (WinNO == 2)
	{
		val = ReadPn(WIN4_CONTROL);
		WritePn(WIN4_CONTROL, val&0xef);
	}
	else if (WinNO == 3)
	{
		val = ReadPn(WIN4_CONTROL);
		WritePn(WIN4_CONTROL, val&0xef);
	}
}

void OSD_GlobalWindowAlpha(U8 winno, U8 level)
{
	if (winno == 0) 
	{
		SetWin0AlphaMode(0);
		SetWin0GlobalAlphaLevel(level);
	}
	else if (winno == 1) 
	{
		SetWin1AlphaMode(0);
		SetWin1GlobalAlphaLevel(level);
	}
	else if (winno == 2) 
	{
		SetWin4AlphaMode(0);
		SetWin4GlobalAlphaLevel(level);
	}
	else if (winno == 3) 
	{
		SetWin4AlphaMode(0);
		SetWin4GlobalAlphaLevel(level);
	}
	OSD_AttrAlpha_Enable(winno);
}

void OSD_PerPixelAlpha(U8 winno)
{
	if (winno == 0) 
	{
		SetWin0AlphaMode(1);
	}
	else if (winno == 1) 
	{
		SetWin1AlphaMode(1);
	}
	OSD_AttrAlpha_Enable(winno);
}

void OSD_ColorKeyAlpha(U8 colorNum, U16 *color, U8 level)
{
	//only win4 has this function
	//level - 0x00(min)~0x7f(max)
	
	SetWin4AlphaMode(1);
	if ((ReadPn(WIN4_CONTROL)&0x04) == 0)
	{
		SetWin4KeyAlphaColor(colorNum, color);
		SetWin4KeyAlphaLevel(colorNum, level);
	}
	OSD_AttrAlpha_Enable(2);
}

void OSD_BlinkIntervalSetting(U8 level)
{
	//00:32frames, 01:16frames, 10:8frames, 11:4frames
	WritePn(OSD_CONTROL2, (level<<6)|ReadPn(OSD_CONTROL2));
}

static U8 GetOsdCpuBusyStatus(void)
{
	if (ReadPn(OSD_STATUS) & 0x40)
	{
		return 1;
	}

	return 0;
}

//=============================================================================
//		SPI DMA (SPI --> Fixed Register)
//=============================================================================
/*static void SPI_ReadData2RegFromSPI( U8* spiaddr, WORD index, DWORD cnt )
{
	U32 SPIAddr = (U32)spiaddr;				// Set Page=5
	//SPIAddr=SPIAddr>>8;
	Printf("\nSPIAddr:%lx\r\n",SPIAddr);

	WritePn( 0xf03, 0xe4);		// Mode = SPI -> fixed register
	WritePn( 0xf0a, 0x03 );				// Read Command
	WritePn( 0xf0b, SPIAddr>>16 );				// SPI address
	WritePn( 0xf0c, SPIAddr>>8 );				// SPI address
	WritePn( 0xf0d, SPIAddr );					// SPI address
	WritePn( 0xf06, index>>8 );				// Buffer address
	WritePn( 0xf07, index );					// Buffer address
	WritePn( 0xf1a, cnt>>16 );					// Read count
	WritePn( 0xf08, cnt>>8 );					// Read count
	WritePn( 0xf09, cnt );						// Read count
	
	WritePn( 0xf04, 0x01 );					// DMA-Read start
}*/

static void EightBitColorExpansionTableSetting(U8 val)
{
	switch (val) // Data
	{
		case 0x04: 
			WritePn(OSD_8BITEXPANSIONTABLE0, 0x00); 
			WritePn(OSD_8BITEXPANSIONTABLE1, 0x01);
			WritePn(OSD_8BITEXPANSIONTABLE2, 0x02); 
			WritePn(OSD_8BITEXPANSIONTABLE3, 0x03);
			WritePn(OSD_8BITEXPANSIONTABLE4, 0x04); 
			WritePn(OSD_8BITEXPANSIONTABLE5, 0x05);
			WritePn(OSD_8BITEXPANSIONTABLE6, 0x06); 
			WritePn(OSD_8BITEXPANSIONTABLE7, 0x07);
			WritePn(OSD_8BITEXPANSIONTABLE8, 0x08); 
			WritePn(OSD_8BITEXPANSIONTABLE9, 0x09);
			WritePn(OSD_8BITEXPANSIONTABLE10, 0x0a); 
			WritePn(OSD_8BITEXPANSIONTABLE11, 0x0b);
			WritePn(OSD_8BITEXPANSIONTABLE12, 0x0c); 
			WritePn(OSD_8BITEXPANSIONTABLE13, 0x0d);
			WritePn(OSD_8BITEXPANSIONTABLE14, 0x0e); 
			WritePn(OSD_8BITEXPANSIONTABLE15, 0x0f);
			break;
		case 0x02: 
			WritePn(OSD_8BITEXPANSIONTABLE0, 0x00); 
			WritePn(OSD_8BITEXPANSIONTABLE1, 0x01);
			WritePn(OSD_8BITEXPANSIONTABLE2, 0x02); 
			WritePn(OSD_8BITEXPANSIONTABLE3, 0x03);
			break;
		case 0x01: 
			WritePn(OSD_8BITEXPANSIONTABLE0, 0x00); 
			WritePn(OSD_8BITEXPANSIONTABLE1, 0x01);
			break;		
	}
}

static void SixteenBitColorExpansionTableSetting(U8 val)
{
	switch(val) // Data
	{
		case 0x01: 
			WritePn(OSD_16BITEXPANSIONTABLE0_H, 0x00); 
			WritePn(OSD_16BITEXPANSIONTABLE0_L, 0x1f);
			WritePn(OSD_16BITEXPANSIONTABLE1_H, 0xff); 
			WritePn(OSD_16BITEXPANSIONTABLE1_L, 0xfe);
			break;
		case 0x02: // for decompress data, the depth can be realized
			WritePn(OSD_16BITEXPANSIONTABLE0_H, 0x00); 
			WritePn(OSD_16BITEXPANSIONTABLE0_L, 0x1f);
			WritePn(OSD_16BITEXPANSIONTABLE1_H, 0xff); 
			WritePn(OSD_16BITEXPANSIONTABLE1_L, 0xfe);
			WritePn(OSD_16BITEXPANSIONTABLE2_H, 0xc8); 
			WritePn(OSD_16BITEXPANSIONTABLE2_L, 0x1f);
			WritePn(OSD_16BITEXPANSIONTABLE3_H, 0xce); 
			WritePn(OSD_16BITEXPANSIONTABLE3_L, 0x5f);
			break;
		case 0x04: 
			WritePn(OSD_16BITEXPANSIONTABLE0_H, 0x00); 
			WritePn(OSD_16BITEXPANSIONTABLE0_L, 0x1f);
			WritePn(OSD_16BITEXPANSIONTABLE1_H, 0xff); 
			WritePn(OSD_16BITEXPANSIONTABLE1_L, 0xfe);
			WritePn(OSD_16BITEXPANSIONTABLE2_H, 0xc8); 
			WritePn(OSD_16BITEXPANSIONTABLE2_L, 0x1f);
			WritePn(OSD_16BITEXPANSIONTABLE3_H, 0xce); 
			WritePn(OSD_16BITEXPANSIONTABLE3_L, 0x5f);
			WritePn(OSD_16BITEXPANSIONTABLE4_H, 0xc8); 
			WritePn(OSD_16BITEXPANSIONTABLE4_L, 0x00);
			WritePn(OSD_16BITEXPANSIONTABLE5_H, 0xce); 
			WritePn(OSD_16BITEXPANSIONTABLE5_L, 0x00);
			WritePn(OSD_16BITEXPANSIONTABLE6_H, 0xc8); 
			WritePn(OSD_16BITEXPANSIONTABLE6_L, 0xff);
			WritePn(OSD_16BITEXPANSIONTABLE7_H, 0xce); 
			WritePn(OSD_16BITEXPANSIONTABLE7_L, 0xff);
			WritePn(OSD_16BITEXPANSIONTABLE8_H, 0xc8); 
			WritePn(OSD_16BITEXPANSIONTABLE8_L, 0x00);
			WritePn(OSD_16BITEXPANSIONTABLE9_H, 0xce); 
			WritePn(OSD_16BITEXPANSIONTABLE9_L, 0x00);
			WritePn(OSD_16BITEXPANSIONTABLE10_H, 0x07); 
			WritePn(OSD_16BITEXPANSIONTABLE10_L, 0xe0);
			WritePn(OSD_16BITEXPANSIONTABLE11_H, 0x07); 
			WritePn(OSD_16BITEXPANSIONTABLE11_L, 0xe0);
			WritePn(OSD_16BITEXPANSIONTABLE12_H, 0xff); 
			WritePn(OSD_16BITEXPANSIONTABLE12_L, 0xe0);
			WritePn(OSD_16BITEXPANSIONTABLE13_H, 0xff); 
			WritePn(OSD_16BITEXPANSIONTABLE13_L, 0xe0);
			WritePn(OSD_16BITEXPANSIONTABLE14_H, 0xf8); 
			WritePn(OSD_16BITEXPANSIONTABLE14_L, 0x00);
			WritePn(OSD_16BITEXPANSIONTABLE15_H, 0xf8); 
			WritePn(OSD_16BITEXPANSIONTABLE15_L, 0x00);
			break;
	}
}

void OSD_LoadBmp(const U8 *Bptr, U16 sx, U16 sy, U8 dispMode)
{
	U8 mode=0, val=0;
	U16 width;
	//U32 size;
	const BITMAP* ptr;
	ptr = (const BITMAP *)Bptr;

	//Printf("\n**OSD_Loading");

	//window0 or window1
	if (dispMode == 0x08)
	{
		if ((ptr->compression&0x0f) != 0x00)
		{
			WritePn(OSD_RLCCTRL, 0x02);  // Reset Cp
			WritePn(OSD_RLCCTRL, 0x11); 	 // Enable Cp Mode
			WritePn(OSD_RLCDATACNT, ptr->compression);// Databit|Countbit
		}
		else
			WritePn(OSD_RLCCTRL, 0x00);  // Bypass Cp Mode

		switch (ptr->color_depth&0x0f) // Data
		{
			case 0x04:
				val = 0x03;
				break;
			case 0x02:
				val = 0x02;
				break;
			case 0x01:
				val = 0x01;
				break;
			default:
				val = 0x00;
				break;
		}

		mode = ReadPn(OSD_MODE) & 0x38;
		OSD_SetBitmapColorWriteMode(mode | 0x00 | 0x04 | val); //MCU WRITE |1 byte per pixel |  Bit expansion

		width = (ptr->width);  //+3)>>2<<2;	 By Jason , no need alignment
	}
	//window4
	else if (dispMode == 0x10)
	{
		if ((ptr->compression&0x0f) != 0x00)
		{
			WritePn(OSD_RLCCTRL, 0x02);  // Reset Cp
			WritePn(OSD_RLCCTRL, 0x11); 	 // Enable Cp Mode
			WritePn(OSD_RLCDATACNT, (ptr->compression)&0x0f);// 0 mean 16 bit mode|Countbit
		}
		else
			WritePn(OSD_RLCCTRL, 0x00);  // Bypass Cp Mode

		switch (ptr->color_depth & 0x0f) // Data
		{
			case 0x08:
				val=0x03;
				break;
			case 0x04:
				val=0x03;
				break;
			case 0x02:
				val=0x02;
				break;
			case 0x01:
				val=0x01;
				break;
			default:
				val=0x00;
				break;
		}

		mode = ReadPn(OSD_MODE) & 0x38;
		OSD_SetBitmapColorWriteMode(mode|0x00|0x00|val);  //MCU WRITE |2 byte per pixel |  Bit expansion
		//osdformat=ReadPn(WIN4_CONTROL)&0xf1;
		//WritePn(WIN4_CONTROL,osdformat|0x02);// 000=YCbCr422, 001=RGB565, 010=RGB4444, 011=RGB1444
		SetWindow4OSDFormat(RGB565);
		width = ptr->width;
	}
	//Printf("\n**OSD_test0");
	SetDestinationStartLocation(sx, sy);
	//Printf("\nsx:%x\r\n",sx);
	//Printf("\nsy:%x\r\n",sy);
	SetSourceDestinationSize(width, ptr->height);

	OSDHardwareEnable();
	SetFillTransferBitmapWriteStart(1);

	//Printf("\n**OSD_test1");
	//SPI_ReadData2Reg(ptr->bmpdata, 0x07+2, 313728/*ptr->data_length*/ );
	//Printf("\nptr->bmpdata:%lx\r\n",ptr->bmpdata);
	SPI_ReadData2Reg(ptr->bmpdata, OSD_WDATAPORT, (ptr->data_length+2));
	//SPI_ReadData2RegFromSPI(ptr->bmpdata, 0x07+2, 313728/*ptr->data_length*/ );
	//Printf("\nptr->data_length:%lx\r\n",ptr->data_length);
	//Printf("\n**OSD_test2");
	while (GetOsdCpuBusyStatus())
		;
	//Printf("\n**OSD_CPUBusy");
	while(GetTransferFillStatusIfDone())
		;
	//Printf("\n**OSD_IfDone");
	SetFillTransferBitmapWriteStart(0);

	WritePn(OSD_RLCCTRL, 0x00); 	 // Disable Cp Mode
}

void OSD_LoadFont(const U8 *Bptr, U16 sx, U16 sy, U8 dispMode, U16 Font_NumIndex)
{
	U8 mode=0,val=0,osdformat;
	U8 Font_W, Font_H,BITS;
	U16 size;
	//U8 *Fptr;
	U32 Fptr,offset;
	const FONTINFO* ptr;
	ptr = (const FONTINFO *)Bptr;

	BITS = (ptr->bits_per_pixel)&0x0f;

	//window0 or window1
	if (dispMode == 0x08)
	{
		if ((ptr->compression&0x0f) != 0x00)
		{
			WritePn(OSD_RLCCTRL, 0x02);  // Reset Cp
			WritePn(OSD_RLCCTRL, 0x11); 	 // Enable Cp Mode
			WritePn(OSD_RLCDATACNT, ptr->compression);// Databit|Countbit
		}
		else
			WritePn(OSD_RLCCTRL, 0x00);  // Bypass Cp Mode

		switch (ptr->bits_per_pixel & 0x0f) // Data
		{
			case 0x04:
				val=0x03;
				break;
			case 0x02:
				val=0x02;
				break;
			case 0x01:
				val=0x01;
				break;
			default:
				val=0x00;
				break;
		}

		EightBitColorExpansionTableSetting(BITS);

		mode = ReadPn(OSD_MODE)&0x38;
		OSD_SetBitmapColorWriteMode(mode|0x00|0x04|val); //MCU WRITE |1 byte per pixel |  Bit expansion
	}
	//window4
	else if (dispMode == 0x10)
	{
		if ((ptr->compression&0x0f) != 0x00)
		{
			WritePn(OSD_RLCCTRL, 0x02);  // Reset Cp
			WritePn(OSD_RLCCTRL, 0x11); 	 // Enable Cp Mode
			//WritePn(OSD_RLCDATACNT,(ptr->compression)&0x0f);// 0 mean 16 bit mode|Countbit
			WritePn(OSD_RLCDATACNT, ptr->compression);// Databit|Countbit
		}
		else
			WritePn(OSD_RLCCTRL, 0x00);  // Bypass Cp Mode

		switch (ptr->bits_per_pixel & 0x0f) // Data
		{
			case 0x08:
				val=0x03;
				break;
			case 0x04:
				val=0x03;
				break;
			case 0x02:
				val=0x02;
				break;
			case 0x01:
				val=0x01;
				break;
			default:
				val=0x00;
				break;
		}

		SixteenBitColorExpansionTableSetting(BITS);

		mode = ReadPn(OSD_MODE)&0x38;
		OSD_SetBitmapColorWriteMode(mode|0x00|0x00|val);  //MCU WRITE |2 byte per pixel |  Bit expansion
		//osdformat=ReadPn(WIN4_CONTROL)&0xf1;
		//WritePn(WIN4_CONTROL,osdformat|0x02);// 000=YCbCr422, 001=RGB565, 010=RGB4444, 011=RGB1444
		SetWindow4OSDFormat(RGB565);
	}
	
	#ifdef Keil_C51
	if (Use_UnicodeFont == 1) //use for unicode font
	{
		offset = ((U32)Font_NumIndex)*8;
		SPI_ReadData2xdata(UnicodeIndexStartAddress+offset,UnicodeIndexBuffer,8);
		//Printf("\nUnicodeIndexBuffer[0]=%bx,UnicodeIndexBuffer[1]=%bx,UnicodeIndexBuffer[2]=%bx,UnicodeIndexBuffer[3]=%bx,UnicodeIndexBuffer[4]=%bx,UnicodeIndexBuffer[5]=%bx,UnicodeIndexBuffer[6]=%bx,UnicodeIndexBuffer[7]=%bx,\r\n",UnicodeIndexBuffer[0],UnicodeIndexBuffer[1],UnicodeIndexBuffer[2],UnicodeIndexBuffer[3],UnicodeIndexBuffer[4],UnicodeIndexBuffer[5],UnicodeIndexBuffer[6],UnicodeIndexBuffer[7]);
		Unicode_Font_char_info[0].character_offset_address=UnicodeIndexBuffer[3];
		Unicode_Font_char_info[0].character_offset_address=(Unicode_Font_char_info[0].character_offset_address<<8)+UnicodeIndexBuffer[2];
		Unicode_Font_char_info[0].character_offset_address=(Unicode_Font_char_info[0].character_offset_address<<8)+UnicodeIndexBuffer[1];
		Unicode_Font_char_info[0].character_offset_address=(Unicode_Font_char_info[0].character_offset_address<<8)+UnicodeIndexBuffer[0];
		//Unicode_Font_char_info[0].character_offset_address=UnicodeIndexBuffer[3]<<24+UnicodeIndexBuffer[0];
		Unicode_Font_char_info[0].character_width=UnicodeIndexBuffer[4];
		Unicode_Font_char_info[0].character_height=UnicodeIndexBuffer[5];
		Unicode_Font_char_info[0].character_size=UnicodeIndexBuffer[7];
		Unicode_Font_char_info[0].character_size=(Unicode_Font_char_info[0].character_size<<8)+UnicodeIndexBuffer[6];
		//Printf("\nUnicode_Font_char_info[0].character_offset_address=%lx,Unicode_Font_char_info[0].character_width=%bx,Unicode_Font_char_info[0].character_height=%bx,Unicode_Font_char_info[0].character_size=%x\r\n",Unicode_Font_char_info[0].character_offset_address,Unicode_Font_char_info[0].character_width,Unicode_Font_char_info[0].character_height,Unicode_Font_char_info[0].character_size);
		//Printf("\nFont_NumIndex=%x\r\n",Font_NumIndex);
		Font_NumIndex = 0;
	}
	#endif
	
	Fptr   = (ptr->character_data) + ((ptr->character_info + Font_NumIndex)->character_offset_address);
	size   = (ptr->character_info + Font_NumIndex)->character_size;
	Font_W = (ptr->character_info + Font_NumIndex)->character_width;
	Font_H = (ptr->character_info + Font_NumIndex)->character_height;

	//according to bits_per_pixel to comfirm Font' width, here gain the total pixels that can be divided exactly
	switch (ptr->bits_per_pixel)
	{
		case 1:
			Font_W = (Font_W+7)>>3<<3;
			break;
		case 2:
			Font_W = (Font_W+3)>>2<<2;
			break;
		case 4:
			Font_W = (Font_W+1)>>1<<1;
			break;
	}
	
	SetDestinationStartLocation(sx, sy);
	SetSourceDestinationSize((U16)Font_W, (U16)Font_H);

	OSDHardwareEnable();
	SetFillTransferBitmapWriteStart(1);

	SPI_ReadData2Reg(Fptr, OSD_WDATAPORT, (size+2) );
	//Printf("\nString_Fptr:%lx\r\n",Fptr);
	//Printf("\nString_size:%x\r\n",size);
	
	while (GetOsdCpuBusyStatus())
		;
	while (GetTransferFillStatusIfDone())
		;

	SetFillTransferBitmapWriteStart(0);

	WritePn(OSD_RLCCTRL, 0x00); 	 // Disable Cp Mode
}

static void SetMainPathOSDSelection(U8 mainpath)
{
	WritePn(OSD_SELECT_FORPATH, ReadPn(OSD_SELECT_FORPATH)|mainpath);
}

static void SetSubPathOSDSelection(U8 subpath)
{
	WritePn(OSD_SELECT_FORPATH, ReadPn(OSD_SELECT_FORPATH)|(subpath<<4));
}

static void SetOSDSelectionForPath(U8 Main, U8 Sub)
{
	SetMainPathOSDSelection(Main);
	SetSubPathOSDSelection(Sub);
}

void OSD_ShowWindowBmp(U8 WinNO, U8 on)
{
	U8 dat;

	OSD_WaitDisplayBlank(1);
	SetOSDSelectionForPath(0x03, 0x03);

	if (WinNO == 0)
	{
		dat = ReadPn(WIN0_CONTROL);
		if (on)
			WritePn(WIN0_CONTROL, dat | 0x01);
		else
			WritePn(WIN0_CONTROL, dat & 0xfe);
	}
	else if (WinNO == 1)
	{
		dat = ReadPn(WIN1_CONTROL);
		if (on)
			WritePn(WIN1_CONTROL, dat | 0x01);
		else
			WritePn(WIN1_CONTROL, dat & 0xfe);
	}
	else if (WinNO == 2)
	{
		dat = ReadPn(WIN4_CONTROL);
		if (on)
			WritePn(WIN4_CONTROL, dat | 0x01);
		else
			WritePn(WIN4_CONTROL, dat & 0xfe);
	}
	else if (WinNO == 3)
	{
		dat = ReadPn(WIN4_CONTROL);
		if (on)
			WritePn(WIN4_CONTROL, dat | 0x01);
		else
			WritePn(WIN4_CONTROL, dat & 0xfe);
	}
}

void OSD_Layer_Init(void)
{
	WritePn(OSD_CONTROL2, 0x02);	// Update right away

	//---set Window memory address base
	OSD_SetWindow0MemoryPositionBase(WIN_START);
	OSD_SetWindow0MemoryHSize(WIN_BUFX/64);
	OSD_SetWindow0MemoryVSize(WIN_BUFY/64);
	OSD_SetWindow1MemoryPositionBase(WIN_START);
	OSD_SetWindow1MemoryHSize(WIN_BUFX/64);
	OSD_SetWindow1MemoryVSize(WIN_BUFY/64);
	OSD_SetWindow4MemoryPositionBase(WIN_START);
	OSD_SetWindow4MemoryHSize(WIN_BUFX/64);
	OSD_SetWindow4MemoryVSize(WIN_BUFY/64);
 
	//---set source memory address base
	OSD_SetSourceMemoryPositionBase(WIN_START);
	OSD_SetSourceMemoryHSize(WIN_BUFX/64);

	//---set destination memory address base
	OSD_SetDestinationMemoryPositionBase(WIN_START);
	OSD_SetDestinationMemoryHSize(WIN_BUFX/64);
}	

void OSD_WaitWindowBlank(U8 winno, U8 Cnt)
{
	U8 i, j;

	if (winno == 0)
		j = 1;
	else if (winno == 1)
		j = 2;
	else
		j = 8;

	for (i=0; i<Cnt; i++)
	{
		while((ReadPn(OSD_VERTICALACTIVE_STATUS) & j) == 0)
			;	
		while((ReadPn(OSD_VERTICALACTIVE_STATUS) & j) != 0)
			;	
	}
}

void OSD_WaitOSDBlank(U8 Cnt)
{
	U8 i;

	WritePn(OSD_VERTICALACTIVE_STATUS, 0x10);			// clear to 0
	for (i=0; i<Cnt; i++)
	{
		while ((ReadPn(OSD_VERTICALACTIVE_STATUS) & 0x10) == 0)
			;	
	}
}

void OSD_WaitDisplayBlank(U8 Cnt)
{
	U8 i;

	WritePn(OSD_VERTICALACTIVE_STATUS, 0x20);			// clear to 0
	for (i=0; i<Cnt; i++)
	{
		while ((ReadPn(OSD_VERTICALACTIVE_STATUS) & 0x20) == 0)
		{
			;
		}
	}
}

#ifndef DP80390
void OSD_DrawLine(U16 x1, U16 y1, U16 x2, U16 y2, U16 color, U8 DispMode)
{
	S32 dx, dy, e, i, x, y;
	
	dx = x2-x1;
	dy = y2-y1;
	x  = x1;
	y  = y1;
	
	if ((dx>=0) && (dy>=0) && (dy<=dx))
	{
		e = 2*dy-dx;
		for (i=0; i<=dx; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			x++;
			e = e+2*dy;
			if (e >= 0)
			{
				y++;
				e = e-2*dx;
			}
		}
	}
	else if ((dx>=0) && (dy>=0) && (dy>dx))
	{
		e = 2*dx-dy;
		for (i=0; i<=dy; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			y++;
			e = e+2*dx;
			if (e >= 0)
			{
				x++;
				e = e-2*dy;
			}
		}
	}
	else if ((dx<0) && (dy>=0) && (dy<=-dx))
	{
		e = 2*dy+(-dx);
		for (i=0; i<=(-dx); i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			x--;
			e = e+2*dy;
			if (e >= 0)
			{
				y++;
				e = e-2*(-dx);
			}
		}
	}
	else if ((dx<0) && (dy>=0) && (dy>-dx))
	{
		e = 2*(-dx)-dy;
		for (i=0; i<=dy; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			y++;
			e = e+2*(-dx);
			if (e >= 0)
			{
				x--;
				e = e-2*dy;
			}
		}
	}
	else if ((-dx>=0) && (-dy>=0) && (-dy<=-dx))
	{
		e = 2*(-dy)-(-dx);
		for (i=0; i<=-dx; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			x--;
			e = e+2*(-dy);
			if (e >= 0)
			{
				y--;
				e = e-2*(-dx);
			}
		}
	}
	else if ((-dx>=0) && (-dy>=0) && (-dy>-dx))
	{
		e = 2*(-dx)-(-dy);
		for (i=0; i<=-dy; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			y--;
			e = e+2*(-dx);
			if (e >= 0)
			{
				x--;
				e = e-2*(-dy);
			}
		}
	}
	else if ((-dx<0) && (-dy>=0) && (-dy<=dx))
	{
		e = 2*(-dy)+(dx);
		for (i=0; i<=(dx); i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			x++;
			e = e+2*(-dy);
			if (e >= 0)
			{
				y--;
				e = e-2*(dx);
			}
		}
	}
	else if ((-dx<0) && (-dy>=0) && (-dy>dx))
	{
		e = 2*(dx)-(-dy);
		for (i=0; i<=-dy; i++)
		{
			OSD_BlockFill(x, y, 1, 1, color, DispMode);//pdc->SetPixel(x,y,RGB(0,255,0));
			y--;
			e = e+2*(dx);
			if (e >= 0)
			{
				x++;
				e = e-2*(-dy);
			}
		}
	}
}
#endif

